﻿using Flurl.Http;
using LiteDB;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Mirai.Net.Api.Contract;
using Mirai.Net.Api.Model;
using Mirai.Net.Core;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Mirai.Net.Api
{
    public class MiraiListener : BackgroundService
    {
        private readonly MiraiClient miraiClient;
        private readonly MiraiDbContext miraiDbContext;

        public MiraiListener(MiraiClient miraiClient, IServiceProvider provider)
        {
            this.miraiClient = miraiClient;
            this.miraiDbContext = provider.CreateScope().ServiceProvider.GetRequiredService<MiraiDbContext>();
        }
        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            return ListenAsync(stoppingToken);
        }

        private async Task ListenAsync(CancellationToken stoppingToken)
        {
            Log.Information("Mirai 机器人平台启动");
            while (true)
            {
                try
                {
                    await miraiClient.ConnectAsync();
                    break;
                }
                catch
                {
                    await Task.Delay(1000);
                }
            }
            Log.Information("Mirai 机器人连接成功");

            MiraiData.Robot = miraiDbContext.Robots.Include(x => x.Listeners).FirstOrDefault();
            while (MiraiData.Robot == null)
            {
                Log.Information("Mirai 机器人平台没有配置机器人");
                await Task.Delay(1000);
            }
            while (!stoppingToken.IsCancellationRequested)
            {
                FetchMessageResponse response = null;
                try
                {
                    await miraiClient.VerifyAsync(MiraiData.Robot.QQ);
                    response = await miraiClient.FetchMessagesAsync();
                    if (response.Code != 0)
                    {
                        await Task.Delay(100);
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    Log.Error("异常", ex);
                    await Task.Delay(5000);
                    continue;
                }
                foreach (JObject data in response.Data)
                {
                    try
                    {
                        var type = Enum.Parse<RobotEvent>(data.Value<string>("type"));
                        Log.Information("Mirai 机器人平台监听到事件:" + type.ToString());
                        var listener = MiraiData.Robot.Listeners.FirstOrDefault(x => x.RobotEvent == type);
                        switch (type)
                        {
                            case RobotEvent.FriendMessage:
                                var friendMessage = JsonConvert.DeserializeObject<FriendMessage>(data.ToString());
                                switch (listener.ValidateType)
                                {
                                    case ValidateType.NoValidate:
                                        break;
                                    case ValidateType.RemoteValidate:
                                        try
                                        {
                                            Log.Information("通知:" + listener.Url);
                                            var responseMessage = await listener.Url.WithHeader("content-type", "application/json").PostJsonAsync(friendMessage);
                                            if (responseMessage.ResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                                            {
                                                await miraiClient.SendFriendMessageAsync(friendMessage.Sender.Id, await responseMessage.GetJsonAsync());
                                            }
                                        }
                                        catch (FlurlHttpException ex)
                                        {
                                            Log.Information("异常", ex);
                                            await miraiClient.SendFriendMessageAsync(friendMessage.Sender.Id, await ex.GetResponseStringAsync());
                                        }
                                        break;
                                }
                                break;
                            case RobotEvent.BotJoinGroupEvent:

                                break;
                            case RobotEvent.NewFriendRequestEvent:
                                var newFriendMessage = JsonConvert.DeserializeObject<MemberJoinRequestMessage>(data.ToString());
                                switch (listener.ValidateType)
                                {
                                    case ValidateType.NoValidate:
                                        await miraiClient.AgreeMemberJoinGroupAsync(newFriendMessage.EventId, newFriendMessage.FromId, newFriendMessage.GroupId, 0, string.Empty);
                                        break;
                                    case ValidateType.RemoteValidate:
                                        try
                                        {
                                            Log.Information("通知:" + listener.Url);
                                            var responseMessage = await listener.Url.WithHeader("content-type", "application/json").PostJsonAsync(newFriendMessage);
                                            if (responseMessage.ResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                                            {
                                                await miraiClient.AgreeNewFriendAsync(newFriendMessage.EventId, newFriendMessage.FromId, newFriendMessage.GroupId, 0, string.Empty);
                                            }
                                            else
                                            {

                                                await miraiClient.AgreeNewFriendAsync(newFriendMessage.EventId, newFriendMessage.FromId, newFriendMessage.GroupId, 1, await responseMessage.GetStringAsync());
                                            }
                                        }
                                        catch (FlurlHttpException ex)
                                        {
                                            Log.Information("异常", ex);
                                            await miraiClient.AgreeNewFriendAsync(newFriendMessage.EventId, newFriendMessage.FromId, newFriendMessage.GroupId, 1, await ex.GetResponseStringAsync());
                                        }
                                        break;
                                }
                                break;
                            case RobotEvent.GroupMessage:

                                break;
                            case RobotEvent.MemberJoinRequestEvent:
                                var joinMessage = JsonConvert.DeserializeObject<MemberJoinRequestMessage>(data.ToString());
                                switch (listener.ValidateType)
                                {
                                    case ValidateType.NoValidate:
                                        await miraiClient.AgreeMemberJoinGroupAsync(joinMessage.EventId, joinMessage.FromId, joinMessage.GroupId, 0, string.Empty);
                                        break;
                                    case ValidateType.RemoteValidate:
                                        try
                                        {
                                            Log.Information("通知:" + listener.Url);
                                            var responseMessage = await listener.Url.WithHeader("content-type", "application/json").PostJsonAsync(joinMessage);
                                            if (responseMessage.ResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                                            {
                                                await miraiClient.AgreeMemberJoinGroupAsync(joinMessage.EventId, joinMessage.FromId, joinMessage.GroupId, 0, string.Empty);
                                            }
                                            else
                                            {

                                                await miraiClient.AgreeMemberJoinGroupAsync(joinMessage.EventId, joinMessage.FromId, joinMessage.GroupId, 1, await responseMessage.GetStringAsync());
                                            }
                                        }
                                        catch (FlurlHttpException ex)
                                        {
                                            Log.Information("异常", ex);
                                            await miraiClient.AgreeMemberJoinGroupAsync(joinMessage.EventId, joinMessage.FromId, joinMessage.GroupId, 1, await ex.GetResponseStringAsync());
                                        }
                                        break;
                                }
                                break;
                            case RobotEvent.MemberJoinEvent:

                                break;

                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "机器人出现异常");
                    }
                }

                await Task.Delay(100);
            }
        }
    }
}
